#ifndef REGEX_H_
#define REGEX_H_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

#define FALSE     0
#define TRUE      1

#define ANY_CHAR  '.'
#define NEGATED_FLG '^'

#define MATCH_START '^'
#define MATCH_END '$'

#define SQUARE_BRACKET_LEFT '['
#define SQUARE_BRACKET_RIGHT ']'
#define BRACKET_LEFT '('
#define BRACKET_RIGHT ')'
#define BRACE_LEFT '{'
#define BRACE_RIGHT '}'
#define COMMA ','

#define MINOR '-'
#define STAR '*'
#define PLUS '+'
#define QUESTION_MARK '?'

#define OP_OR '|'

#define ESCAPE_CHAR '\\'

#define SCREEN_WIDTH 120

struct regex_unit_t
{
	char acStr[255+1];
	char cRe;                           // waste
    int iMin;                           // Match Min
    int iMax;                           // Match Max
    char cNegatedFlg;
}; 

struct regex_list_t
{
	struct regex_unit_t stRegex;
    struct regex_list_t* pstNext;
};

struct regex_group_t
{
    int iMin;                           // Match count min
    int iMax;                           // Match count max
    char cOr;                           // 1:or、0:and
    int iReferNo;                       // () 
    int iReferBackNo;                   // \num
    struct regex_list_t* pstRegList;
    struct regex_group_t* pstChild;
    struct regex_group_t* pstBrother;
}; 

struct regex_all_t 
{
	char cHead;
	char cTail;                         // not use
    struct regex_group_t* pstRegex;
}; 

// for print
struct regex_group_print_info
{
    int iLevel;
    int iPos;
    struct regex_group_t* pstRegex;
};

struct refer_info 
{
    char* pcStart;
    char* pcEnd;
};

struct refer_info_list
{
    char* pcStr;
    struct refer_info astReferInfo[99];
};

// analyse regex functions
char* analyse_all(char* pcRegex, struct regex_group_t** ppstRegex);

// test use tools
void print_regex_tree(struct regex_group_t* pstRegex);
void print_regex(struct regex_group_t* pstRegex);

// match
int match_all(char* pcStr, struct regex_all_t* pstRegexAll);

void free_regex(struct regex_group_t*);

char* get_errorstr();

#ifdef NOEXTERN
int g_iReferNo = -1;
struct refer_info_list g_stReferInfos;
int g_errorno = 0;
char* g_errorpos = NULL;
#else
extern int g_iReferNo;
extern struct refer_info_list g_stReferInfos;
extern int g_errorno;
extern char* g_errorpos;
#endif

#endif // REGEX_H_

